﻿using System;
using System.Reflection;
using System.Web.Security;
using Lbb.User.Helpers;

namespace Lbb.User.Providers
{
    /// <summary>
    /// 管理 SQL Server 数据库中 ASP.NET 应用程序的成员资格信息存储。
    /// </summary>
    /// <author>Chiron</author>
    public class SqlMembershipProvider : System.Web.Security.SqlMembershipProvider
    {

        #region Events
        /// <summary>
        /// 完成创建用户事件
        /// </summary>
        public event EventHandler<UserEventArgs> CreatedUser;
        /// <summary>
        /// 删除用户事件
        /// </summary>
        public event EventHandler<UserEventArgs> DeletingUser;
        /// <summary>
        /// 完成删除用户事件
        /// </summary>
        public event EventHandler<UserEventArgs> DeletedUser;
        #endregion

        public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
        {
            if (!MemberUser.UserNameReg.IsMatch(username))
            {
                status = MembershipCreateStatus.InvalidUserName;
                return null;
            }
            var user = base.CreateUser(username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
            var mUser = status == MembershipCreateStatus.Success ? new MemberUser(user) : null;
            if (mUser != null && CreatedUser != null) CreatedUser.Invoke(this, new UserEventArgs { User = mUser });
            return mUser;
        }

        public override bool DeleteUser(string username, bool deleteAllRelatedData)
        {
            var user = GetUser(username, false);
            if (user == null) return false;

            var mUser = new MemberUser(user);
            var eventArgs = new UserEventArgs { User = mUser };
            if (DeletingUser != null) DeletingUser.Invoke(this, eventArgs);
            if (eventArgs.Cancel) return false;

            var result = base.DeleteUser(username, deleteAllRelatedData);
            if (result && DeletedUser != null) DeletedUser.Invoke(this, new UserEventArgs { User = mUser });
            return result;
        }

        public override string ResetPassword(string username, string passwordAnswer)
        {
            if (EnablePasswordReset && passwordAnswer == null && !string.IsNullOrEmpty(username))
            {
                var providerType = typeof(System.Web.Security.SqlMembershipProvider);
                var bindingAttr = BindingFlags.NonPublic | BindingFlags.Instance;
                var GetPasswordWithFormat = providerType.GetMethod("GetPasswordWithFormat", bindingAttr);
                var EncodePassword = providerType.GetMethod("EncodePassword", bindingAttr);

                var args = new object[] { username, false, 0, "", 0, "", 0, 0, false, DateTime.MinValue, DateTime.MinValue };
                GetPasswordWithFormat.Invoke(this, args);
                var passwordSalt = (string)args[5];
                var passwordFormat = (int)args[4];
                var newPassword = Membership.GeneratePassword((MinRequiredPasswordLength < 14) ? 14 : MinRequiredPasswordLength, MinRequiredNonAlphanumericCharacters);

                using (var repository = RepositroyHelper.GetUserRepository())
                {
                    repository.SetPassword(
                        ApplicationName,
                        username,
                        (string)EncodePassword.Invoke(this, new object[] { newPassword, passwordFormat, passwordSalt }),
                        passwordSalt,
                        DateTime.UtcNow,
                        passwordFormat
                    );
                }

                return newPassword;
            }
            else
            {
                return base.ResetPassword(username, passwordAnswer);
            }
        }
    }
}
